Add UDS peer credentials on Posix.Context - #192
Open
VictorDebray wants to merge 3 commits into
Open
Conversation
Gives us kernel-validated peer credentials for Unix domain socket
connections as a field on `HTTP2ServerTransport.Posix.Context`.
Adds `HTTP2ServerTransport.Posix.UDSCredentials { pid, uid, gid }` and a
matching `udsCredentials` field on `Posix.Context`. The field is populated
in the existing channel-init closure that already populates
`peerCertificate` / `peerCertificateChain`, by calling a new internal
helper in `Sources/GRPCNIOTransportHTTP2Posix/UDSPeerCredentials.swift`
which uses `SocketOptionProvider.unsafeGetSocketOption` to read
`SO_PEERCRED` (Linux) or `LOCAL_PEEREPID` + `LOCAL_PEERCRED` (Darwin).
Returns `nil` for non-UDS channels, on platforms without peer-credential
support, and on any read failure, so nothing changes for existing
transports.
`struct ucred` (Linux) and `struct xucred` (Darwin) are mirrored locally:
glibc 2.36+ guards `ucred` behind `_GNU_SOURCE`, which the Swift Glibc
module does not reliably set, and the Swift Darwin overlay is not
guaranteed to re-export `xucred` across SDK versions.
|
|
Author
|
/easycla |
1 similar comment
Author
|
/easycla |
glbrntt
requested changes
Aug 4, 2026
glbrntt
left a comment
Collaborator
There was a problem hiding this comment.
We'll also need tests for these changes
- Remove the leftover internal TODO comment. - Rename `populateUDSCredentials` to `makeUDSCredentials`: it creates and returns a value rather than populating one in place. - Skip the socket option reads entirely unless the channel is backed by a Unix domain socket. - Spell out the returned type instead of relying on `.init`. - Don't expose `pid_t`/`uid_t`/`gid_t` in public API. Add nominal `ProcessID`, `UserID` and `GroupID` wrappers holding fixed-size integers, following the shape of `SocketAddress.VirtualSocket.ContextID`. - Annotate the new API with `@available(gRPCSwiftNIOTransport 2.10, *)` and bump `nextMinorVersion` so the 2.10 availability macro is defined. - Make `UDSCredentials` `Hashable` with `var` properties, matching the feedback given for `VsockCredentials`. Still outstanding: the Linux `struct ucred` mirror should be replaced by a C shim defining `_GNU_SOURCE`, and tests are still needed.
Replaces the hand-written mirror of Linux's `struct ucred` with a C shim target that defines `_GNU_SOURCE`, following the shape of SwiftNIO's `CNIOLinux`. glibc only declares `struct ucred` when `_GNU_SOURCE` is defined and the Swift Glibc module doesn't reliably set it, which is why the type was previously redeclared in Swift. `CGRPCNIOTransportLinux` defines `_GNU_SOURCE` via `cSettings` and includes <sys/socket.h>, so `ucred` and `SO_PEERCRED` are imported from the platform headers instead of being duplicated. The header is `#ifdef __linux__`-guarded and `#error`s if `_GNU_SOURCE` is somehow absent, and the target is only a dependency on Linux. The Darwin mirror of `struct xucred` is also removed: `xucred` is imported by the Swift Darwin overlay, so it can be used directly. `cr_groups` imports as a fixed-size tuple, which replaces the pointer rebinding that read the primary group out of the local copy.
glbrntt
requested changes
Aug 10, 2026
| /// recorded by the kernel when the connection was established; they are not | ||
| /// re-read per request. | ||
| @available(gRPCSwiftNIOTransport 2.10, *) | ||
| public struct UDSCredentials: Hashable, Sendable { |
Collaborator
There was a problem hiding this comment.
None of these types are specific to server transport so shouldn't be nested within HTTP2ServerTransport. I think they can be moved to their own file in the core module.
Comment on lines
+331
to
+337
| public var pid: ProcessID | ||
|
|
||
| /// The user ID of the peer process. | ||
| public var uid: UserID | ||
|
|
||
| /// The group ID of the peer process. | ||
| public var gid: GroupID |
Collaborator
There was a problem hiding this comment.
Can we spell these out rather than abbreviating them?
Comment on lines
+103
to
+111
| // C-module exposing Linux declarations which glibc guards behind `_GNU_SOURCE`, such as | ||
| // `struct ucred` and `SO_PEERCRED`. | ||
| .target( | ||
| name: "CGRPCNIOTransportLinux", | ||
| dependencies: [], | ||
| cSettings: [ | ||
| .define("_GNU_SOURCE") | ||
| ] | ||
| ), |
Collaborator
There was a problem hiding this comment.
Apologies, it turns out that we don't need to go as far as this: we can just add the C settings to the posix module, no need for a C module at all.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gives us kernel-validated peer credentials for Unix domain socket connections as a field on
HTTP2ServerTransport.Posix.Context.Adds
HTTP2ServerTransport.Posix.UDSCredentials { pid, uid, gid }and a matchingudsCredentialsfield onPosix.Context. The field is populated in the existing channel-init closure that already populatespeerCertificate/peerCertificateChain, by calling a new internal helper.The helper reads
SO_PEERCRED(Linux) orLOCAL_PEEREPID+LOCAL_PEERCRED(Darwin).Returns
nilfor non-UDS channels, on platforms without peer-credential support, and on any read failure, so nothing changes for existing transports.